home *** CD-ROM | disk | FTP | other *** search
- /*
- Hsoi's App Shell ©1995-1997 John C. Daub. All Rights Reserved.
-
- CONTACT INFO: Internet: <mailto:hsoi@eden.com>
- <http://www.eden.com/~hsoi/>
-
- Hsoi's App Shell (HAS) is a mix of an application skeleton and demo app. It can be
- used as the basis for the creation of a Macintosh application, or could just
- be a "library" of code for "neat" things.
-
- My philosophy with HAS has been to both be a teaching/learning resource,
- a code repository, and perhaps a place to make the lives of programmers easier.
-
- On the first part, I remember how it was for me when i started to program and
- program Macs. It wasn't impossible, but I did run into a lot of problems and
- obstacles: sparse, difficult to understand, or nonexistant documentation; lack
- of sample code; sample code in a language I didn't understand; sample code
- that was out of date; things no longer supported by their authors; no one wanting
- to answer my questions; no one able to answer my questions; etc...
-
- So, from that, I wanted to see if I could try to make the lives of future
- Mac programmers a little bit easier by hoping to save them from going through
- the same problems I had to go through.
-
- On the second part, I would find sample code for things, but many times they'd
- be in a language I didn't use (like in Pascal or C++), or the code would be
- old and out of date (especially in trying to write working code for PowerPC
- Macs, to take advantage of latest technologies, or whatever), or whatever
- reason. I just am trying to put a lot of stuff all in one place...it's
- easier when you can just find things in one place instead of having to look
- all over creation. With HAS, you'll still have to look in other places to
- find things, but I at least hope to be able to give you exact locations of
- things (like URLs) to make your search easier.
-
- And lastly, I just hope to make things easier, not only in all of the above,
- but also in the pocketbook. I learned a lot from great books by Scott Knaster
- and Dave Mark, and I highly recommend their books...the more you can learn
- and the more you can know, the more you can do. But I know what it's like
- to be poor, and to be a software developer, it can get to be a costly undertaking.
-
- So, by providing this as freeware, I hope that it can make someone's life
- a bit easier :)
-
- Now...more about HAS....
-
- HAS is System 7 dependant. I could have put in stuff to allow backwards
- compatability to System 6 (at least), but i did not want to do this since
- previous system software usage is becoming more and more scarce, plus there
- are many features that HAS tries to demostrate that just don't exist (or
- can't exist) under anything less than System 7.
-
- HAS also tries to exploit many of these things in System 7 (MacOS 7) and
- is working towards being as compliant as possible with Copland ("System 8"
- or MacOS 8) and all the latest developments for the MacOS. Basically,
- I'm trying to help people keep up to date with the latest and greatest
- things so that any software you're currently developing will have as
- long of a self-life as possible.
-
- On that note, one nice thing about HAS over books is that as new things
- come out, I can immediately update the shell to reflect those new changes
- and features. Books will always be a great thing, but for a book to
- reflect a new direction Apple wishes to go in, that will take some time
- for a new edition/version to come out. Idealisticly speaking, I could
- get a demonstration of a new technology into HAS in as much time as it
- takes me to learn the new technology and write some samples for it.
-
- I first started to write it with THINK C 7.0.4, then moved to CodeWarrior 4,
- and up through CW8. It was worked on generating 68k code, and then compiled
- with the PPC compiler to obtain native PowerMac code. I have worked to try to have
- the app work as nicely as possible with CodeWarrior, but compilation with
- THINK C and MPW I have not worked on, but probably will in the future.
-
- Developed on a Macintosh IIvx with 8 megs of RAM (and RamDoubler), 80 meg
- internal hard drive, 127 meg, 540 meg, and 1 gig external hard drives (all from APS),
- MacsBug 6.5.2, CodeWarrior8, EvenBetterBusError, DisposeResource, DoubleTrouble,
- ZoneRanger, and various other toys...
-
- What do YOU need to use HAS? A MacOS based computer (be it a Mac from Apple
- or a clone...now there's something strange to say...clone) with at least
- a 68020 processor or PowerPC processor (HAS programs and HAS itself needs
- at least a 68020 or PPC chip, and at least System 7...and on the note of
- System software version, the later the better, like 7.5.x would be great,
- but for many things like drag and drop, scripting, etc...you can have at least
- 7.1 and acquire various system extensions from <ftp://ftp.info.apple.com/> )
- The more the RAM the merrier, but I feel comfortable with 8 megs of real
- RAM and using RamDoubler. Disk space...up to your project, but hopefully
- the HAS distribution will not take up more than 10 megs (with compiled
- binaries, object code, etc) os disk space. And finally, a lot of patience,
- perserverance (sp?), and if you're into it, caffiene and nicotine. ;)
-
- Portions of this code are obviously not mine. WASTE is copyright © 1993-1996
- Marco Piovanelli; WASTE Object Handler's by Michael Kamprath; MovableModal
- Library by Marco Piovanelli; WETabs also by Marco.
-
- I've also based some of HAS on the code of others, then did a lot of
- modifying and changing to that code. This start code came from:
- Show_help by James W. Walker; Scott Knaster and Keith Rollin's book,
- "Macintosh Programming Secrets"; Gary Little and Tim Swihart's, "Programming
- for System 7"; John Norstad's NewsWatcher; Tom Bender's Tex-Edit+;
- Metrowerks sample code; and some stuff was taken from Apple DTS sample code (and heavily
- modified and rewritten to work with the shell and MacOS progress/developments)
- and various other Apple things (like Inside Macintosh, etc.). Of course,
- various help from the readers of the WASTE mailing list, the readers of
- comp.sys.mac.programmer.help
-
- If I have forgotten anyone (person, company, etc.) in this "rights"
- notice, I do apologize. I am not trying to take credit for your work, and
- if I did forget you, please contact me and we'll remedy the situation
- with due haste.
-
- Also, HAS was originally based upon the WASTE Demo App code written by Marco
- Piovanelli. So if you see a lot of similarities between HAS and the WEDemo,
- this is why. I cannot thank Marco enough for all his support, generousity, help,
- and kind words. I owe much to Marco.
-
- For more detailed legal information about HAS and using it, please see the
- "HAS Legal Info" file that you should have received with this distribution. If
- you do not have access to this file, please write to me and I'll send you
- a copy.
- */
-
-
- /* HASMain.c from Hsoi's App Shell. ©1995-1996 John C. Daub. All rights reserved
-
- This file contains the main() function, plus the stuff necessary to start
- up the application (gestalt checks, intializations, etc...those things
- necessary to do before we get to the main event loop).
-
- Additionally, it contains the main event loop (why not..where else would
- I put it), and all those things necessary to the quitting of the program
- (clean ups, etc).
- */
-
- #pragma mark ••• #includes •••
-
- #ifndef _WASTE_
- #include "WASTE.h"
- #endif
- #include "HASGlobals.h"
- #ifndef __HSOIS_APP_SHELL__
- #include "HASMain.h"
- #endif
- #include "HASDialogs.h"
- #include "HASMenus.h"
- #include "HASUtilDialogs.h"
- #include "HASUtilCursors.h"
- #include "HASMenuWindows.h"
- #include "HASAppleEvents.h"
- #include "HASEventDispatch.h"
- #include "HASMiscEvents.h"
- #include "HASWindows.h"
- #include "HASDragNDrop.h"
- #include "HASUtilities.h"
- #include "HASPrinting.h"
- #include "HASPreferences.h"
- #include "HASSoundSpeech.h"
- #ifndef _WASTEOBJECTS_
- #include "WASTE_Objects.h"
- #endif
- #ifndef __SPEECH__
- #include <Speech.h>
- #endif
-
- #pragma mark -
- #pragma mark ••• globals •••
-
- // some static UPP's for our drag manager stuff
-
- static DragTrackingHandlerUPP sTrackingHandlerUPP;
- static DragReceiveHandlerUPP sReceiveHandlerUPP;
-
-
- #pragma mark -
-
- // Procedures and functions
-
- /*
- * main()...where it all starts and ends! pretty simple eh?
- */
-
- void main( void )
- {
- // initalize everything
-
- HsoiInitialize();
-
- // and here we go! HsoiEventLoop() handles it all...
-
- HsoiEventLoop();
-
- ExitToShell(); // trust me....
-
- return;
- }
-
-
- /*
- * Here we do all the initialization stuff...get all the managers set up, configure stuff
- * etc etc...
- */
-
- void HsoiInitialize( void )
- {
- short i = 0;
- long scrapResult = 0;
- PScrapStuff scrapReturn = 0;
- Boolean alreadySpoken;
- OSErr err;
-
- // start out by expanding the application heap zone...
-
- MaxApplZone();
-
- // get us some more master pointers...
-
- for ( i = 1; i <= 20; i++ )
- MoreMasters(); // can't hurt to have more handles...who knows :)
-
- // call all the standard macintosh toolbox initialization functions
-
- InitGraf((Ptr) &qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- FlushEvents(everyEvent,nil);
- TEInit(); // tho we use WASTE for text stuff, dialogs, etc all use TextEdit,
- // so don't remove this!
- InitDialogs(nil);
- InitCursor();
-
- // let's make sure we can run on this computer b4 we go any further
-
- HsoiCheckForKosherSystem();
-
- // get this app/shell's resource fork id
-
- gAppResourceFork = CurResFile();
-
- // get our cursors set up
-
- HsoiSetUpCursors();
-
- // set to our wait cursor while we take care of the rest of the startup stuff.
-
- SetCursor( *gWaitCursor );
-
- // take care of the preferences (read them in or create if necessary)
-
- HsoiInitPrefs();
-
- // init our speech stuff
-
- HsoiInitSpeechStuff();
-
- // if desk scrap is too large, unload it
-
- scrapReturn = InfoScrap();
- if ( scrapReturn->scrapSize > kScrapThreshold )
- scrapResult = UnloadScrap();
-
- // make sure some of our important global variables are set to the proper values
-
- gInBackground = false;
- gQuitting = false;
- gCursorRgn = NewRgn(); // (forces cursor-move event right away)
-
- // initialize Edition Manager
-
- err = InitEditionPack();
- if ( err != noErr )
- HsoiDoError( rErrorStrings, errFailedEditionInit, err, kErrDeath );
-
- // install AppleEvent Handlers
-
- HsoiDoAEInstallation();
-
- // install Text Services Manager...to support double-byte script systems
-
- if ( gHasTextServices )
- {
- err = InitTSMAwareApplication();
- if ( err != noErr )
- HsoiDoError( rErrorStrings, errFailedTSMInit, err, kErrDeath );
- }
-
- // install default drag handlers
-
- if ( gHasDragAndDrop )
- {
- sTrackingHandlerUPP = NewDragTrackingHandlerProc(HsoiMyTrackingHandler);
- sReceiveHandlerUPP = NewDragReceiveHandlerProc(HsoiMyReceiveHandler);
-
- err = InstallTrackingHandler( sTrackingHandlerUPP, nil, nil );
- if ( err != noErr )
- HsoiDoError( rErrorStrings, errFailDragTrackInit, err, kErrDeath );
-
- err = InstallReceiveHandler( sReceiveHandlerUPP, nil, nil );
- if ( err != noErr )
- HsoiDoError( rErrorStrings, errFailDragReceiveInit, err, kErrDeath );
- }
-
-
- // initialize the handlers to handle WASTE objects: sounds, PICTs, files
- // this is all from Michael Kamprath's WASTE Object Handlers
-
- err = InstallAllWASTEObjHandlers(nil);
- if ( err != noErr )
- HsoiDoError( rErrorStrings, errFailObjectInit, err, kErrDeath );
-
- InitWASTEObjectHandlers();
-
- // initialize the printing routines
-
- err = HsoiInitPrintingStuff();
- // and we should check for the error here....
-
- // set our standard dialog filter callback procedure into a global UPP
-
- HsoiGetMyStandardDialogFilter();
-
- // and just to be cute before we kick into things, let's say something for the
- // nice users...
-
- if ( gMyPrefs.doSplashScreen )
- alreadySpoken = HsoiDoSplashScreen();
- else
- alreadySpoken = false;
-
- if ( gHasSpeechManager && gMyPrefs.doStartupSpeech && !alreadySpoken )
- {
- SpeakString( "\pWelcome to Hsoi's App Shell." );
- while ( SpeechBusy() != nil )
- ; // do nothing, just wait until it's done speaking
- }
-
- // set up the menus
-
- HsoiSetUpMenus();
-
- // get our Windows menu UPP's set up
-
- HsoiInitMenuWindowUPPs();
-
- // make sure we don't have any weird cursors
-
- InitCursor();
-
- return;
-
- }
-
- /*
- * This function will check to make sure that we have a computer that we can work
- * with...if the computer lacks something, we'll have to make ammends...
- */
-
- void HsoiCheckForKosherSystem( void )
- {
- OSErr err = noErr;
- long reply = 0;
- SysEnvRec gMac;
-
-
- // first, let's see if we have a computer that we can use.
-
- // This function checks to see if the machine is at least a MacPlus.
-
- // Frankly, this might be pointless...I'd assume that if this is running on a computer
- // running less than system 7 and/or on a system less than a MacPlus, this call might
- // fail with an unimplimented trap error...in fact, a lot of this kosher system checking
- // might fail for that reason if not on a machine fitting these, but i dunno since
- // I don't have such a computer to test this all on.
-
-
- err = SysEnvirons( curSysEnvVers, &gMac );
-
- if ( (err < 0 ) || (gMac.machineType < 0) ) // -2 is Mac XL/Lisa, -1 is original Mac with 64k ROMs
- HsoiDoError( rErrorStrings, errWimpyROMs, gMac.machineType, kErrDeath );
-
- // and now check for System 7 with Gestalt. This will fail if Gestalt doesn't
- // exist and/or if System 7 isn't the system on the machine
-
- if ( !HsoiSystem7Available() )
- {
- HsoiDoError( rErrorStrings, errWimpySystem, gMac.systemVersion, kErrDeath );
- gQuitting = true;
- return;
- }
-
- // The next check is to make sure that WaitNextEvent() is implimented on the
- // machine. System 7 (and hopefully future systems) should always have
- // WaitNextEvent, but just in case...read somewhere that it's good to be
- // a little redundant
-
-
- if ( !HsoiTrapAvailable( _WaitNextEvent ) )
- HsoiDoError( rErrorStrings, errWeirdSystem, gMac.systemVersion, kErrDeath );
-
- // let's check for AppleEvents
-
- err = Gestalt( gestaltAppleEventsAttr, &reply );
- if ( !(( err == noErr ) && ( BTST( reply, gestaltAppleEventsPresent ))) )
- HsoiDoError( rErrorStrings, errNoAppleEvents, err, kErrDeath );
-
- // do we have ColorQuickDraw on this machine??
-
- err = Gestalt( gestaltQuickdrawVersion, &reply );
- gHasColorQD = !( err || ( reply < gestalt8BitQD ) );
- if ( err || !gHasColorQD )
- HsoiDoError( rErrorStrings, errNoColorQD, err, kErrDeath );
-
- // Again, being redundant. Making sure the System 7 FSSpec file handler calls exist
-
- // check for FSspec records
-
- err = Gestalt( gestaltFSAttr, &reply );
- if ( !(( err == noErr ) && ( BTST( reply, gestaltHasFSSpecCalls))) )
- HsoiDoError( rErrorStrings, errNoFSSpec, err, kErrDeath );
-
- // check for StandardGetFile() and StandardPutFile()
-
- err = Gestalt( gestaltFSAttr, &reply );
- if ( !(( err == noErr) && ( BTST( reply, gestaltStandardFile58))) )
- HsoiDoError( rErrorStrings, errNoFSSpec, err, kErrDeath );
-
- // make sure we can use the FindFolder() function
-
- err = Gestalt( gestaltFindFolderAttr, &reply );
- if ( !(( err == noErr) && ( BTST(reply, gestaltFindFolderPresent ))) )
- HsoiDoError( rErrorStrings, errNoFSSpec, err, kErrDeath );
-
- // see if we have the Alias Manager present
-
- err = Gestalt( gestaltAliasMgrAttr, &reply );
- if ( !(( err == noErr ) && ( BTST( reply, gestaltAliasMgrPresent ))) )
- HsoiDoError( rErrorStrings, errNoAliasMgr, err, kErrDeath );
-
- // see if we have the Edition Manager present
-
- err = Gestalt( gestaltEditionMgrAttr, &reply );
-
- // since i don't have the Edition Manager (Publish and Subscribe) stuff written
- // yet (later release), we don't need to check for an error right now
-
- // if ( !((err == noErr) && ( BTST( reply, gestaltEditionMgrPresent ))) )
- // HsoiDoError( rErrorStrings, errNoEditionManager, err, kErrDeath );
-
- // check for the notification manager
-
- err = Gestalt( gestaltNotificationMgrAttr, &reply );
- if ( !((err == noErr ) && ( BTST(reply, gestaltNotificationPresent ))) )
- {
- HsoiDoError( rErrorStrings, errNoNotification, err, kErrDeath );
- gHasNotification = false;
- }
- else
- gHasNotification = true;
-
- // determine whether or not the Drag Manager is available
-
- gHasDragAndDrop = ( (Gestalt( gestaltDragMgrAttr, &reply ) == noErr ) &&
- BTST( reply, gestaltDragMgrPresent ) );
-
- #if GENERATINGCFM
- // additional check needed if DragLib is weak-linked
- gHasDragAndDrop = gHasDragAndDrop && (&NewDrag != nil);
- #endif
-
- // unless it's vital to your application that you have drag and drop installed,
- // don't bother calling DeathAlert()...as of this writing, having drag and drop
- // is not vital to an app's existance
-
- // if ( !gHasDragAndDrop )
- // HsoiDoError( rErrorStrings, errNoDragAndDrop, 0, kErrDeath );
-
- // determine whether or not the Text Services Manager is available
-
- gHasTextServices = ( Gestalt( gestaltTSMgrVersion, &reply ) == noErr );
-
- // again, unless it's vital to your app's existance to have the TSM stuff, don't
- // call DeathAlert...as of this writing, it's not vital, mostly cause for me
- // I am not using a double-byte script system
-
- // if ( !gHasTextServices )
- // HsoiDoError( rErrorStrings, errNoTextServices, 0, kErrDeath );
-
-
- // see if they have a sound input device (so they can record sounds)
- // this gestalt check taken right from Michael Kamprath's WASTE Object Handlers
- // in his CreateNewSoundObject() routine (we'll need to check this for HsoiAdjustMenus())
-
- err = Gestalt( gestaltSoundAttr, &reply );
- if ( (err == noErr) && ( BTST(reply,gestaltHasSoundInputDevice)) )
- gCanRecordSound = true;
- else
- gCanRecordSound = false;
-
- // it's not vital to have a sound input device (still can play sounds), but if it's
- // vital to you, you might want to insert an error handler in here. e.g.:
-
- // if ( !gCanRecordSound )
- // HsoiDoError( rErrorStrings, errCantRecordSounds, err, kErrDeath );
-
-
- // now to see if we have the Speech Manager present. Hsoi's App Shell as
- // a whole isn't dependant upon the existance of the Speech Manager, but some
- // functionality is, so let's make sure we got it
-
- err = Gestalt( gestaltSpeechAttr, &reply );
- if ( (err == noErr ) && ( BTST(reply, gestaltSpeechMgrPresent) ) )
- gHasSpeechManager = true;
- else
- gHasSpeechManager = false;
-
- // and if it's vital for you to have speech stuff, you can uncomment this error checker
-
- // if ( !gHasSpeechManager )
- // HsoiDoError( rErrorStrings, errNoSpeechManager, err, kErrDeath );
-
- // check to see if the new ColorPicker is present
-
- err = Gestalt( gestaltColorPicker, &reply );
- if (err == noErr)
- gHasColorPicker = true;
- else
- gHasColorPicker = false;
-
- // not necessary to have this (no fatal error handling)...if no color picker, we'll
- // just call GetColor instead of PickColor
-
-
- // and we should probably be checking for more neat-o things the app is dependant
- // upon, but that's left as an exercise for you :)
- // besides, the majority of these things are System 7 dependant (ya got System 7, ya
- // got such-and-such). a lot of this is just redundant to be sure.
-
- return;
-
- }
-
-
-
- /* HsoiEventLoop()...the main meat of all this...
-
- Much of this was taken directly from "Macintosh Programming Secrets" 2nd ed. by
- Scott Knaster and Keith Rollin from their example in Chap. 4, "Dialogs".
- */
-
- void HsoiEventLoop( void )
- {
-
- Boolean gotEvent = false;
- EventRecord event;
- Boolean passToDialog = false;
- DialogRef theDialog = nil;
- short itemHit = 0;
- Boolean itemWasHit = false;
- WindowRef window = nil;
-
-
- while( !gQuitting )
- {
- // if we got a periodic task, we'll need to hog the processor, else give it up
- // to other running applications (at least the Finder)
-
- gSleepTime = ( gPeriodicTask ? 1 : MAXLONG );
-
- // the ever popular meat of everything...getting the event!
-
- gotEvent = WaitNextEvent( everyEvent, &event, gSleepTime, gCursorRgn );
-
- // give text services a chance to intercept this event
-
- if ( gHasTextServices )
- TSMEvent( &event );
-
- // adjust cursor shape and set mouse region
- // (we assume event->where is the current mouse position in global corrdinates
- // if event->what <= osEvt; high-level events store the event ID there
-
- if ( event.what <= osEvt )
- HsoiAdjustCursor( event.where, gCursorRgn );
-
- // This routine must be called periodically (ideally in the event loop).
- // It checks for and deals with any tasks that objects might need
- // (such as checking for and deallocating unneeded sound buffers) - Michael Kamprath
-
- window = gFirstWindow;
- while ( window )
- {
- DoObjectTasks( HsoiGetWindowWE(window) );
- window = (WindowRef)HsoiGetNextWindow(window);
- }
-
- // This dialog stuff is to handle the modeless dialog, (and also the movable
- // modal progree bar (the "Doing some long task..dum dee dum" one)). It handles
- // events to these dialogs. Doesn't really handle things like <Return>
- // but it works. It's from Knaster's MPS book.
-
-
- passToDialog = true;
- if ( ( FrontWindow() == nil )
- || ( event.what == diskEvt )
- || ( ( event.what == keyDown ) && ( ( event.modifiers & cmdKey ) != 0 )))
- passToDialog = false;
-
- // if there's a keyDown with the cmdKey, usually we want to reject it, however
- // if it's a cmd-. on the movablemodal dialog, let's take it so we can dismiss
- // the dialog with a cmd-. yea i know...messy
-
- if ( (!passToDialog) && ((event.what == keyDown) || event.what == autoKey) &&
- (event.modifiers & cmdKey) && ((event.message & charCodeMask) == '.') &&
- (FrontWindow() == (WindowRef)gMovableModalDialog) )
- {
- passToDialog = true;
- }
-
- // and it doesn't get any prettier...not only are we checking for certain
- // events for a cmd-., but also we have to take the notification manager
- // into account...
-
- if ( passToDialog )
- {
- if ( IsDialogEvent ( &event ) )
- {
- itemWasHit = DialogSelect( &event, &theDialog, &itemHit );
-
- // check for cmd-. on the movablemodal progress dialog
-
- if ( ((event.what == keyDown) || (event.what == autoKey)) &&
- (event.modifiers & cmdKey) &&
- ((event.message & charCodeMask) == '.' ) &&
- (theDialog == gMovableModalDialog) )
- {
- itemWasHit = true; // fake a hit on the cancel button
- itemHit = ok; // and say it was on the cancel (ok) button
- }
-
- if ( itemWasHit )
- {
- HsoiDoDialogHit( theDialog, itemHit );
- }
-
- // if we have the movable modal progress dialog up, we need it to intercept suspend/resume
- // events so that the Notification Manager stuff can get posted correctly
-
- if ( gHasNotification )
- {
- if ( ( event.what == osEvt ) && ( ((event.message >> 24) & 0x0FF ) == suspendResumeMessage ) &&
- gInModalState && gPeriodicTask )
- {
- gotEvent = true;
- }
- else
- gotEvent = false;
- }
- }
- }
-
-
- // dispatch the events
-
- if ( gotEvent )
- {
- HsoiDoEvent( &event );
- gSleepTime = 0; // force early idle after non-idle event (?)
- }
- else
- HsoiDoIdle();
-
- // take care of any periodic tasks...
-
- if ( gPeriodicTask )
- HsoiDoMainLoopTasks();
-
- // if we're speaking, run the hiliter
-
- if ( gHiliting )
- HsoiRunHiliter( &event );
-
- }
-
- return;
- }
-
-
- /* HsoiDoMainLoopTasks() takes care of handling things like working on a repeated job, i.e.
- a progress indicator */
-
- void HsoiDoMainLoopTasks( void )
- {
- if ( gPeriodicTask )
- {
-
- RotateCursor( TickCount() ); // keep our watch animating/spinning
-
- gPeriodicTask = !HsoiSetProgressDelta( 1 );
- if ( !gPeriodicTask )
- {
- // if we finish and the app is in the background, let's use the
- // Notification Manager to alert the user that it's all done
-
- if ( gHasNotification && gInBackground )
- {
- HsoiPostNMMessage();
- }
-
- // just hide the dialog
-
- HideWindow( GetDialogWindow(gMovableModalDialog) );
-
- // reset our global cause we're no longer in a modal state
-
- gInModalState = false;
-
- // get back to an arrow
-
- HsoiStopManualSpinning();
-
- // and make our menus look cool
-
- HsoiAdjustMenus();
- }
- }
-
- return;
- }
-
-
- /*
- Called when the user selects Quit (or cmd-Q).
-
- Takes care of making sure we can quit the application all nice and clean.
- */
-
- OSErr HsoiCleanUp( SavingOption saving )
- {
- WindowRef window = nil;
- OSErr err = noErr;
-
-
- // close all the windows and ask if they want to save the contents (if needed)
-
- do
- {
- window = FrontWindow();
- if ( window )
- {
- err = HsoiDoClose( closingApplication, saving, window );
- if ( err != noErr )
- return err;
- }
- } while ( window );
-
- // the user didn't cancel for any reason, so we must want to quit
-
- gQuitting = true;
-
- // remove drag handlers
-
- if ( gHasDragAndDrop )
- {
- RemoveTrackingHandler( sTrackingHandlerUPP, nil );
- RemoveReceiveHandler( sReceiveHandlerUPP, nil );
- }
-
- // clean up object handlers
-
- ExitWASTEObjectHandlers();
-
- // dispose of the standard dialog filter proc (not really necessary, but we'll do
- // it anyways.
-
- DisposeRoutineDescriptor( gMyStdDlogFilterProc );
-
- // if we have a speech channel, dump it
-
- if ( gSpeechOn )
- DisposeSpeechChannel( gSpeechChannel );
-
- // notify text services that we're closing down
-
- if ( gHasTextServices )
- CloseTSMAwareApplication();
-
- // write out the prefs file
-
- if ( gWritePrefs )
- HsoiWritePrefs();
-
- return err;
- }
-
-